package com.example.bluetooth;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.example.bluetooth.ble.manager.BluetoothControl;
import com.example.bluetooth.ble.service.BluetoothLeService;
import com.example.bluetooth.ble.utils.BluetoothControlUtil;
import com.example.bluetooth.ble.utils.DataProcessUtil;
import com.example.bluetooth.commonUtil.BleBluetoothUtil;
import com.example.bluetooth.commonUtil.IBluetoothUtil;

import org.json.JSONArray;
import org.json.JSONException;

import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    //蓝牙权限
    public static final int REQUEST_OPEN_BT_CODE = 0x01;
    private static final int REQUESTCODE_COARSE_LOCATION = 0x02;
    private static final String PERMISSION_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;//"android.permission.ACCESS_COARSE_LOCATION";

    private IBluetoothUtil bluetoothUtil;

    public static String TAG = "DBCZ2";

    private static final String ACTION_LINK_BLUE_TOOTH = "action_link_blue_tooth";
    private static final String ACTION_SEND_ORDER = "action_send_order";
    private static final String ACTION_DISCONNECT_BLUETOOTH = "action_disconnect_bluetooth";
    //    private CallbackContext callbackContext;
    private BluetoothControl mBluetoothControl;

    private long startLinkTime = 0;
    private String addressToConnect;
    private int connectTimeOut;
    private boolean disconnectByUser = false;
    private int disconnectByUserOutTime = 5;
    private int disconnect_by_user_state = 0x00;
    private static final int DISCONNECT_BY_USER_STATE_SUCCESS = 0x01;
    private static final int DISCONNECT_BY_USER_STATE_ING = 0x00;

    private BlueBroadcastReceiver mBlueBroadcastReciver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initBluetooth();
        findViewById(R.id.connect_tv).setOnClickListener(this);
        findViewById(R.id.send_tv).setOnClickListener(this);
        findViewById(R.id.disconnect_tv).setOnClickListener(this);
        findViewById(R.id.install_app_tv).setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        try {
            switch (v.getId()) {
                case R.id.connect_tv:
                    JSONArray array = new JSONArray();
                    array.put("54:6C:0E:35:78:18");
                    eventProcess(ACTION_LINK_BLUE_TOOTH, array);
                    break;
                case R.id.send_tv:
                    JSONArray array1 = new JSONArray();
                    array1.put("123456");
                    eventProcess(ACTION_SEND_ORDER, array1);
                    break;
                case R.id.disconnect_tv:
                    eventProcess(ACTION_DISCONNECT_BLUETOOTH, null);
                    break;
                case R.id.install_app_tv:
                    startActivity(new Intent(this, InstallAppActivity.class));
                    break;
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private boolean eventProcess(String action, JSONArray args) throws JSONException {
        Log.i(TAG, action);
        if (action.equals(ACTION_LINK_BLUE_TOOTH)) {
            if (args == null || args.getString(0) == null || args.getString(0).length() == 0 || "null".equals(args.getString(0))) {
                Log.e(TAG, "address null");
                return true;
            }
            addressToConnect = args.getString(0).replaceAll(":", "").toUpperCase();
            //addressToConnect 转为AB:CD:1E:2F:3G 格式
            String reg = "(.{2})";
            addressToConnect = addressToConnect.replaceAll(reg, "$0:");
            addressToConnect = addressToConnect.substring(0, addressToConnect.length() - 1);
//            connectTimeOut=args.getInt(1);
            connectTimeOut = connectTimeOut <= 0 ? 30 : connectTimeOut;//默认30秒

            //如果需要在子线程执行
            openBlueTooth(addressToConnect);
            return true;
        }
        if (action.equals(ACTION_SEND_ORDER)) {
            if (args == null || args.getString(0) == null || args.getString(0).length() == 0 || "null".equals(args.getString(0))) {
                Log.e(TAG, "order null");
                return true;
            } else {
                writeData(args.getString(0));
            }
            return true;
        }
        /*清除蓝牙连接*/
        if (action.equals(ACTION_DISCONNECT_BLUETOOTH)) {
            disConnect();
            return true;
        }
        return false;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (requestCode == REQUEST_OPEN_BT_CODE) {
            if (resultCode == 0) {//拒绝了蓝牙开启
                showToast("连接蓝牙设备需要开启蓝牙");
            } else if (resultCode == -1) {//蓝牙开启
                openBlueTooth(addressToConnect);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        cleanUpBluetooth();
    }

    private void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    /**
     * 写数据
     *
     * @param data
     */
    private void writeData(String data) {
        if (BluetoothControlUtil.getInstance().getConnectState()) {
            BluetoothControlUtil.getInstance().writeData(data.replaceAll(" ", ""), mHandler);
        } else {
            showToast("请先连接蓝牙设备");
        }
    }

    private boolean hasPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            //校验是否已具有模糊定位权限
            if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_OPEN_BT_CODE);
                return false;
            } else {
                showToast("已经有权限了！");
                return true;
            }
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_OPEN_BT_CODE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {//蓝牙权限开启成功
                showToast("蓝牙权限已开启");
                openBlueTooth(addressToConnect);
            } else {
                showToast("蓝牙权限未开启,请设置");
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    /**
     * 判断权限
     * 打开蓝牙
     * 尝试连接
     *
     * @param address
     */
    private void openBlueTooth(final String address) {
        if (!hasPermission()) return;
        //权限检查
        if (bluetoothUtil == null) {
            bluetoothUtil = new BleBluetoothUtil() {
                @Override
                public void onFoundDevices(BluetoothDevice device, int rssi, byte[] scanRecord) {
                    if (device.getAddress().equals(address)) {
                        if (isLinkTargetDevices(address)) {
                            linkToDevices(device.getAddress());
                        }
                        bluetoothUtil.stopScan();
                    }
                }
            };
        }
        if (bluetoothUtil.init(this)) {
            Log.d(TAG, "init success");
        } else {
            showToast("Your device does not support BLE bluetooth");
            return;
        }

        if (!bluetoothUtil.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, REQUEST_OPEN_BT_CODE);
        } else {
            if (!isLinkTargetDevices(address)) {
                bluetoothUtil.startScan();
                startLinkTime = System.currentTimeMillis();
                linkToDevices(address);
                mHandler.postDelayed(new CheckConnectState(this), 500);
            }
        }
    }

    /**
     * 判断当前给定的蓝牙地址是否已经连接
     *
     * @param address
     * @return
     */
    public boolean isLinkTargetDevices(String address) {
        if (!BluetoothControlUtil.getInstance().getConnectState())
            return false;
        if (!getCurrentAddress().equals(address)) {
            BluetoothLeService.getInstance().disconnect();
            return false;
        } else {
            Log.d(TAG, "success");
            showToast("已经连接当前设备");
            return true;
        }
    }

    /**
     * 尝试连接设备
     *
     * @param address
     */
    public void linkToDevices(final String address) {
        new Thread() {
            @Override
            public void run() {
                if (getCurrentAddress().equals(address)) {
                    if (!BluetoothControlUtil.getInstance().getConnectState()) {
                        System.out.println("=====================================正在连接蓝牙设备=====================================");
                        BluetoothLeService.getInstance().connect(address);
                    }
                    return;
                }
//                showToast("正在连接蓝牙设备");
                System.out.println("=====================================正在连接蓝牙设备=====================================");
                BluetoothControlUtil.getInstance().setCurrentAddress(address);
                BluetoothLeService.getInstance().connect(address);
            }
        }.start();
    }

    /**
     * 获取当前连接的Mac地址，空返回""
     *
     * @return
     */
    public String getCurrentAddress() {
        return BluetoothControlUtil.getInstance().getCurrentAddress() == null ? "" : BluetoothControlUtil.getInstance().getCurrentAddress();
    }

    private int PERMISSION_DENIED_ERROR = -1;

    private void registerBroadcast() {
        mBlueBroadcastReciver = new BlueBroadcastReceiver(this);
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.START_WRITE_SERVER);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        LocalBroadcastManager.getInstance(this).registerReceiver(mBlueBroadcastReciver, intentFilter);
    }

    private void resetBluetooth() {
        cleanUpBluetooth();
        initBluetooth();
    }

    private void initBluetooth() {
        BluetoothLeService.getInstance().init(this);
        if (mBluetoothControl == null) {
            mBluetoothControl = new BluetoothControl();
            mBluetoothControl.setOnSendResultListener(BluetoothControlUtil.getInstance());
        }
        //注册广播
        mBluetoothControl.registerLocalBroadcast(this);
        if (!BluetoothLeService.getInstance().initialize()) {
            showToast("不支持蓝牙设备");
            return;
        }
        registerBroadcast();
    }


    private void disConnect() {
        if (BluetoothControlUtil.getInstance().getConnectState()) {
            disconnect_by_user_state = DISCONNECT_BY_USER_STATE_ING;
            disconnectByUser = true;
            mHandler.post(new CheckDisconnectState(this));
            isAutoDis = false;
            BluetoothLeService.getInstance().disconnect();
            BluetoothLeService.getInstance().close();
            BluetoothControlUtil.getInstance().setCurrentAddress(null);
            BluetoothControlUtil.getInstance().setConnectState(false);
        } else {
            Log.d(TAG, "未连接，不需要断开");
        }
    }


    private void cleanUpBluetooth() {
        disConnect();
        if (mBluetoothControl != null)
            mBluetoothControl.unregisterLocalBroadcast(this);
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mBlueBroadcastReciver);
    }


    private class CheckDisconnectState implements Runnable {
        private WeakReference<MainActivity> weakReference;

        public CheckDisconnectState(MainActivity dbcz2) {
            this.weakReference = new WeakReference<MainActivity>(dbcz2);
        }

        @Override
        public void run() {
            MainActivity dbcz2 = weakReference.get();
            if (dbcz2 == null) return;
            long startTime = System.currentTimeMillis();
            while (dbcz2.disconnect_by_user_state == dbcz2.DISCONNECT_BY_USER_STATE_ING
                    && (System.currentTimeMillis() - startTime) < 1000 * dbcz2.disconnectByUserOutTime
                    && BluetoothControlUtil.getInstance().getConnectState()) {
                try {
                    Thread.sleep(12);
                } catch (InterruptedException e) {
                }
            }
            if (dbcz2.disconnect_by_user_state == dbcz2.DISCONNECT_BY_USER_STATE_SUCCESS || !BluetoothControlUtil.getInstance().getConnectState()) {
                Log.d(TAG, "success");
            } else {
                Log.e(TAG, "error");
            }
            dbcz2.mHandler.removeCallbacks(this);
        }
    }

    /**
     * 判断蓝牙的连接
     */
    private class CheckConnectState implements Runnable {
        private WeakReference<MainActivity> weakReference;

        public CheckConnectState(MainActivity dbcz2) {
            this.weakReference = new WeakReference<MainActivity>(dbcz2);
        }

        @Override
        public void run() {
            MainActivity dbcz2 = weakReference.get();
            if (dbcz2 == null) return;
            if (dbcz2.startLinkTime == 0) {
                dbcz2.startLinkTime = System.currentTimeMillis();
            }
            while (!BluetoothControlUtil.getInstance().getConnectState() && ((System.currentTimeMillis() - dbcz2.startLinkTime) < 1000 * dbcz2.connectTimeOut)) {
                try {
                    Thread.sleep(12);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //结束扫描
            if (dbcz2.bluetoothUtil != null)
                dbcz2.bluetoothUtil.stopScan();

            if (!BluetoothControlUtil.getInstance().getConnectState()) {//没连接上,重置蓝牙，为下次连接做准备
                Log.e(TAG, "error");
                Log.e(TAG, "ERROR");
                dbcz2.resetBluetooth();
            } else {
                Log.d(TAG, "success");
            }
            dbcz2.startLinkTime = 0;
            //监控结束，回收掉
            dbcz2.mHandler.removeCallbacks(this);
        }
    }


    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BluetoothControl.READ_RESULT:
                    final byte[] data = (byte[]) msg.obj;
                    String strData = DataProcessUtil.getInstance().bytes2HexString(data);
                    Log.d(TAG, strData);
                    String newData = "";
                    for (int i = 0; i < strData.length() / 2 - 1; i++) {
                        newData = newData + strData.substring(i * 2, (i + 1) * 2) + " ";
                    }
                    newData = newData + strData.substring(strData.length() - 2, strData.length());
                    Log.e(TAG, "new Data===" + newData);
                    break;
            }
        }
    };


    private boolean isAutoDis = true;

    private static class BlueBroadcastReceiver extends BroadcastReceiver {

        private WeakReference<MainActivity> weakReference;

        public BlueBroadcastReceiver(MainActivity Dbcz) {
            this.weakReference = new WeakReference<MainActivity>(Dbcz);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            MainActivity dbcz2 = weakReference.get();
            if (dbcz2 == null) return;
            String action = intent.getAction();

            if (action.equals(BluetoothLeService.ACTION_GATT_CONNECTED)) {
                Log.i(dbcz2.TAG, "ACTION_GATT_CONNECTED 蓝牙连接");
            } else if (action.equals(BluetoothLeService.ACTION_GATT_DISCONNECTED)) {
                if (dbcz2.isAutoDis)
                    BluetoothLeService.getInstance().connect(BluetoothControlUtil.getInstance().getCurrentAddress());
                BluetoothControlUtil.getInstance().setConnectState(false);
                if (dbcz2.disconnectByUser) {
                    dbcz2.disconnect_by_user_state = dbcz2.DISCONNECT_BY_USER_STATE_SUCCESS;
                    dbcz2.disconnectByUser = false;
                } else {
                    dbcz2.showToast("蓝牙失去连接");
                }
            } else if (action.equals(BluetoothLeService.START_WRITE_SERVER)) {
                BluetoothControlUtil.getInstance().setConnectState(true);
                Log.i(dbcz2.TAG, "蓝牙准备就绪");
                dbcz2.isAutoDis = true;
                dbcz2.showToast("蓝牙连接成功");
            }
        }
    }
}